package com.caisejingyu.whales.home.devices.printer;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.CountDownTimer;
import android.support.annotation.Nullable;
import android.util.Pair;

import com.caisejingyu.whales.common.BaseApplication;
import com.caisejingyu.whales.home.common.Defines;

import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

import static com.caisejingyu.whales.home.devices.printer.PrinterService.PrinterState.DEVICE_OFFLINE;
import static com.caisejingyu.whales.home.devices.printer.PrinterService.PrinterState.LACK_PAPER;
import static com.caisejingyu.whales.home.devices.printer.PrinterService.PrinterState.PRINTING;
import static com.caisejingyu.whales.home.devices.printer.PrinterService.PrinterState.PRINT_ABLE;


/**
 * Created by guaziorg on 29/11/16.
 */

public class FakePrinter implements PrinterService {
    public static final String ACTION_CUPS = "com.tchip.printer.CupsNotify";
    private static final boolean PRINTER_Offline = false;
    private static final boolean PRINTER_Online = true;
    CupsIntentReceiver mCupsReceiver = new CupsIntentReceiver();
    boolean printer_online;
    int printer_state = 3;
    int job_state = 9;
    boolean lack_paper = false;
    private volatile boolean mIsCancel = false;

    private Queue<PrintTask> printQueue = new LinkedBlockingQueue<>();

    private CountDownTimer countDownTimer = new CountDownTimer(120000, 120000) {
        @Override
        public void onTick(long millisUntilFinished) { }

        @Override
        public void onFinish() {
            PrintUtils.cancelPrint();
            if (printRunnable.printTask != null) {
                printRunnable.printTask.printFinish(printRunnable.printTask.mId, false);
                printRunnable.printTask = null;
            }
            printRunnable.resumeRunner();
        }
    };

    private PrintRunnable printRunnable = new PrintRunnable();

    public FakePrinter() {
        initPrinterState();
        register_receiver();
        initPrinterDriverConfig();
        new Thread(printRunnable).start();
    }

    /**
     * 配置一下打印机驱动的参数
     */
    private void initPrinterDriverConfig() {
        //new PrintDriverConfig().runConfig();
    }

    private void initPrinterState() {
        String lp0 = Shell.exec("/system/bin/ls /dev/usb/lp0");
        if (lp0 == null || lp0.length() == 0) {
            printer_online = false;
        } else {
            printer_online = true;
            PrintUtils.restartCupsd();
            PrintUtils.cancelPrint();
        }
    }

    private void register_receiver() {
        IntentFilter filter = new IntentFilter(ACTION_CUPS);
        RedboxEnv.INSTANCE().context = BaseApplication.getAppContext();
        RedboxEnv.INSTANCE().getContext().registerReceiver(mCupsReceiver, filter);
    }

    public boolean print(String photo, String adi) {
        lack_paper = false;
        //
        String print = new A7ImageProcessor().process(photo, null, adi);
        if (print == null)
            return false;
        return true;
    }

    @Override
    public boolean print(String photo, String rahmen, String adi, IPrintExcute print) {
        lack_paper = false;
        print.setHorizontalOffset(PrintPageConstants.getPrintHorizontalOffset());
        return print.exec(photo, rahmen, adi);
    }

    @Override
    public void print(PrintTask printTask) {
        printQueue.add(printTask);
        printRunnable.resumeRunner();
    }

    @Override
    public PrinterState getPrinterState() {
        if (printer_online == false)
            return DEVICE_OFFLINE;
        if (lack_paper)
            return LACK_PAPER;
        if (printer_state == 3 && job_state == 9) {
            return PRINT_ABLE;
        } else if (job_state == 5) {
            return PRINTING;
        }
        return PRINT_ABLE;
    }

    @Override
    public boolean isPrinting() {
        if (!printer_online) {
            return false;
        }
        if (printer_state == 3 && job_state == 9) {
            return false;
        }
        if (job_state == 5 || lack_paper) {
            return true;
        }
        return false;
    }

    /**
     * 重置打印状态为可打印状态
     */
    @Override
    public void resetPrintState() {
//        printer_state = 3;
//        job_state = 9;
        lack_paper = false;
//        Monitor.INSTANCE().getState().setPrinterState(PRINT_ABLE);
    }

    public boolean isFinishedNow() {
        if (printer_state == 3 && job_state == 9) {
            return true;
        }
        return false;
    }

    @Override
    public boolean isPrintableNow() {
        if (!isDeviceGood())
            return false;
       /* if (lack_paper == true)
            return true;*/
        if (/*lack_paper == false && */printer_state == 3 && job_state == 9) {
            return true;
        }
        return false;
    }

    @Override
    public boolean isDeviceGood() {
        return printer_online;
    }

    @Override
    public boolean isLackPaper() {
        return lack_paper;
    }

    /**
     * 取消缺纸重试打印，由于缺纸可能重试会导致吐白纸情况
     */
    @Override
    public void cancelPrinte() {
        PrintUtils.cancelPrint();
        mIsCancel = true;
    }

    private class CupsIntentReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            try {
                String action = intent.getStringExtra("event");
                switch (action) {
                    case "PrinterStateChanged":
                        printer_state = intent.getIntExtra("printer-state", -1);
                        String reasion = intent.getStringExtra("printer-state-reasons");
                        if (reasion.equals("media-empty-warning")) {
                            PrintServiceFactory.liveDataPrinterState.postValue(Defines.PRINTER_STATE_LACK_PAPER);
                            lack_paper = true;
                        }
                        break;
                    case "JobState"://if==5,print have start
                        job_state = intent.getIntExtra("job-state", -1);
                        if (job_state == 5) {
                            PrintServiceFactory.liveDataPrinterState.postValue(Defines.PRINTER_STATE_PRINTING);
                        }
                        break;
                    case "JobCreated"://4
                        //job_state=intent.getIntExtra("job-state",-1);
                        lack_paper = false;
                        mIsCancel = false;
                        break;
                    case "JobCompleted"://if==9,print have finished
                        job_state = intent.getIntExtra("job-state", -1);
                        printer_state = 3;
                        if (job_state == 7) {//取消打印
                            job_state = 9;
                        }
                        if (mIsCancel && lack_paper) {
                            PrintServiceFactory.liveDataPrinterState.postValue(Defines.PRINTER_STATE_LACK_PAPER);
                        } else if (job_state == 9) {
                            PrintServiceFactory.liveDataPrinterState.postValue(Defines.PRINTER_STATE_PRINT_FINISH);
                            printRunnable.resumeRunner();
                        }
                        break;
                    case "PrinterOnline":
                        printer_online = PRINTER_Online;
                        printer_state = 3;
                        job_state = 9;
                        PrintServiceFactory.liveDataPrinterState.postValue(Defines.PRINTER_STATE_PRINT_ABLE);
//                        Monitor.INSTANCE().getState().setPrinterOnline(true);
                        //Monitor.INSTANCE().getState().setPrinterState(PRINT_ABLE);
                        break;
                    case "PrinterOffline":
                        PrintServiceFactory.liveDataPrinterState.postValue(Defines.PRINTER_STATE_PRINT_OFFLINE);
//                        Monitor.INSTANCE().getState().setPrinterOnline(false);
                        printer_online = PRINTER_Offline;
                        break;
                }
            } catch (Exception e) {
            }
        }
    }

    private class PrintRunnable implements Runnable {

        @Nullable public PrintTask printTask;
        private final Object lock = new Object();

        private boolean pause = false;
        private boolean stop = false;

        /**
         * 调用该方法实现线程的暂停
         */
        void pauseRunner(){
            pause = true;
        }

        /**
         * 调用该方法实现线程的结束
         */
        void stopRunner(){
            resumeRunner();
            stop = true;
        }

        /*
        调用该方法实现恢复线程的运行
         */
        void resumeRunner(){
            pause =false;
            synchronized (lock){
                lock.notify();
            }
        }

        /**
         * 这个方法只能在run 方法中实现，不然会阻塞主线程，导致页面无响应
         */
        void onPause() {
            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void run() {
            while (!stop) {
                try {
                    while (pause) {
                        onPause();
                    }
                    if (printTask != null) {
                        printTask.printFinish(printTask.mId, true);
                        printTask = null;
                    }
                    PrintTask photo = printQueue.poll();
                    if (photo != null) {
                        printTask = photo;
                        printTask.printStart(printTask.mId);
                        countDownTimer.cancel();
                        countDownTimer.start();
                        print(printTask.mPhoto, null, null, PrintFaceFactory.getPrinterFace(PrintPageConstants.getPrintPageType()));
                    }
                    pauseRunner();
                } catch (Exception ignore) { }
            }
        }
    }
}
